package com.think.provider;

import com.think.common.JwtAuthenticationToken;
import com.think.common.RawAccessJwtToken;
import com.think.exception.JwtExpiredTokenException;
import com.think.model.User;
import com.think.util.JwtTokenUtil;
import com.think.util.ValidUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

@Component
@SuppressWarnings("unchecked")
public class JwtAuthenticationProvider implements AuthenticationProvider {
    private static Logger logger = LoggerFactory.getLogger(JwtAuthenticationProvider.class);
    @Value("${jwt.secret}")
    private String jwtSecret;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String token = (String) authentication.getCredentials();

        Claims claimsFromToken = jwtTokenUtil.getClaimsFromToken(token);
        if (!ValidUtil.valid(claimsFromToken)) {
            logger.info("Authorization exception");
            throw new JwtExpiredTokenException("Authorization exception");
        }

        String subject = claimsFromToken.getSubject();

        List<GrantedAuthority> authorities = new ArrayList<>();
        List<Map<String,String>> scopes = claimsFromToken.get("scopes", ArrayList.class);
        for (Map<String, String> scopeMap : scopes) {
            authorities.add(new SimpleGrantedAuthority(scopeMap.get("authority")));
        }

        User user = new User();
        user.setGrantedAuthorities(authorities);
        user.setUsername(subject);

        return new JwtAuthenticationToken(user, user.getAuthorities());
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return (JwtAuthenticationToken.class.isAssignableFrom(authentication));
    }
}